/**
 * 
 */
package IC.lir;

import java.util.List;
import java.util.Map;

import util.LinkedList;

import IC.AST.PropogatingVisitor;
import IC.AST.nodes.*; 
import IC.AST.DefaultVisitor;
import IC.lir.decl.*;

/**
 *	TODO iterate on classes
 *	1. write down labels
 *  2. write literals
 *	3. write DV for each class
 *	4. add code of declared functions, from previous stage, but not for `main'
 *	5. add `main' code
 *
 */
public class LIRGenerator extends DefaultVisitor<Object, Object> 
implements PropogatingVisitor<Object, Object> {
	private		List<LIREntry> 	lir;
	private		Program			root;
	
	/**
	 * constructs a LIR Generator
	 * @param root
	 */
	private LIRGenerator(Program root) {
		lir = new LinkedList<LIREntry>();
		this.root = root;
	}
	
	/**
	 * Generates code for a lowered AST tree
	 * @param prog
	 */
	public static List<LIREntry> Process(Program prog) 
	throws Exception {
		LIRGenerator g = new LIRGenerator(prog);
		prog.accept(g,null);
		return g.lir;
	}

	/**
	 * 1. print string literals
	 * 2. pront dispatch vectors
	 * 3. print code
	 */
	public Object visit(Program that, Object context)
	throws Exception {
		// string literals
		Map<String,String> stringLiterals = that.getStringLiterals();
		for(String s : stringLiterals.keySet()) {
			String val = stringLiterals.get(s);
			lir.add(new StringDecl(val,s));
		}
		
		// dispatch vectors
		for (ClassDecl cls: that.getClasses()) {
			if (!cls.getClassID().equals("Library")) {
				lir.add(cls.getClassInfo().getDVDecl());
			}
		}

		// code
		for (ClassDecl cls: that.getClasses()) {
			if (!cls.getClassID().equals("Library")) {
				cls.accept(this,context);
			}
		}
		
		// main
		lir.addAll(that.getMain().getLirCode());
		
		return null;
	}
	
	
	/**
	 * visit a method
	 * add the method code
	 */
	public Object visit(MethodDecl that, Object context) throws Exception {
		if (root.getMain() != that) {
			lir.addAll(that.getLirCode());
		}
		return null;
	}
}
